/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufc.quixada.adrs.comandos.visit;

import br.ufc.quixada.adrs.interfaces.Comando;
import br.ufc.quixada.adrs.model.Produtor;
import br.ufc.quixada.adrs.model.QuestionarioQualitativo;
import br.ufc.quixada.adrs.model.RelatorioQualitativoResult;
import br.ufc.quixada.adrs.model.Visita;
import br.ufc.quixada.adrs.util.UtilAdrs;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *
 * @author ismaily
 */
public class CmdVisitMontaRelatorioQlPassoCinco implements Comando {

    public String executa(HttpServletRequest request, HttpServletResponse response) {
        //Definição das mensagens de erro que podem ocorrer
        String[] mensagemErro = new String[8];
        mensagemErro[1] = "Por favor, selecione um tipo de resposta.";
        mensagemErro[2] = "Por favor, especifique um período para o relatório.";
        mensagemErro[3] = "Por favor, verifique o preenchemento da data que indica o início do período do relatório.";
        mensagemErro[4] = "Por favor, verifique o preenchemento da data que indica o fim do período do relatório.";
        mensagemErro[5] = "Por favor, selecione um ou alguns filtros para o relatório.";
        mensagemErro[6] = "Período selecionado não contem visitas.";
        mensagemErro[7] = "Por favor, escolha quantidade e/ou porcentagem.";


        //recuperar dados do formulário
        String todosPeriodos = request.getParameter("todosPeriodos");
        Date ini = null;
        String dataIni = request.getParameter("dataInicio");
        if (dataIni != null) {
            ini = UtilAdrs.treatToDate(dataIni);
        }
        Date fim = null;
        String dataFim = request.getParameter("dataFim");
        if (dataFim != null) {
            fim = UtilAdrs.treatToDate(dataFim);
        }

        HttpSession session = request.getSession(true);


        List<String> questoesMarcadas = (ArrayList<String>) session.getAttribute("questoesMarcadas");
        List<Produtor> produtores = (ArrayList<Produtor>) session.getAttribute("produtoresSelecionadoQS");
        List<RelatorioQualitativoResult> result = new ArrayList<RelatorioQualitativoResult>();

        //pegar campos do formulário
        String comparacao = request.getParameter("compResult");
        String quantResut = request.getParameter("quantResult");
        String porcenResult = request.getParameter("porcentResult");
        String tipoResposta = request.getParameter("tipoResposta");



        //validar se os campos foram todos preenchidos devidademente
        int codErro = validaCampos(comparacao, todosPeriodos, dataIni, dataFim, quantResut, porcenResult, tipoResposta);
        if (codErro != 1) {
            session.setAttribute("erro", mensagemErro[codErro * (-1)]); //caso algum erro ocorra retorna para a tela com uma mensgem de erro
            return "/visit/visit_monta_relatorio_ql_passo_cinco.jsp";
        }
        //se não foi marcado a opção todos os periódos e no periódo marcado não há questionário quantitativo, o método retorna uma mensagem de erro
        if (todosPeriodos == null || todosPeriodos.trim().isEmpty()) {
            if (!validaData(ini, fim, produtores)) {
                session.setAttribute("erro", mensagemErro[6]);
                return "/visit/visit_monta_relatorio_ql_passo_cinco.jsp";
            }
        }

        Integer resposta = null;
        if (comparacao == null) {
            resposta = Integer.parseInt(tipoResposta);
            if (resposta.equals(RelatorioQualitativoResult.VALOR_RESPOSTA_NAO_RESPONDIDO)) {
                tipoResposta = RelatorioQualitativoResult.RESPOSTA_NAO_RESPONDIDO;
            }
            if (resposta.equals(RelatorioQualitativoResult.VALOR_RESPOSTA_NAO)) {
                tipoResposta = RelatorioQualitativoResult.RESPOSTA_NAO;
            }
            if (resposta.equals(RelatorioQualitativoResult.VALOR_RESPOSTA_SIM)) {
                tipoResposta = RelatorioQualitativoResult.RESPOSTA_SIM;
            }
            if (resposta.equals(RelatorioQualitativoResult.VALOR_RESPOSTA_SIM_ADEQUADAMENTE)) {
                tipoResposta = RelatorioQualitativoResult.RESPOSTA_SIM_ADEQUADAMENTE;
            }
        }

        //fazer os calculos
        int quantidadeRespostas;
        boolean questaoEstimavitivaMarcada = false;
        double porcenAG3 = 0d;
        double porcenAG4 = 0d;
        RelatorioQualitativoResult r = null;
        for (int i = 0; i < questoesMarcadas.size(); i++) {
            quantidadeRespostas = 0;
            r = new RelatorioQualitativoResult();
            r.setQuestao(questoesMarcadas.get(i));

            if (questoesMarcadas.get(i).equals("AG3") || questoesMarcadas.get(i).equals("AG4")) {
                questaoEstimavitivaMarcada = true;
                this.getMediaValorQuestaoNumeerica(questoesMarcadas.get(i), produtores, todosPeriodos, ini, fim, r);
            }
            if (comparacao != null) {
                getComparacao(questoesMarcadas.get(i), produtores, todosPeriodos, ini, fim, r);
            } else {
                if ((questoesMarcadas.get(i).equals("AG3") || questoesMarcadas.get(i).equals("AG4")) && tipoResposta.equals(RelatorioQualitativoResult.RESPOSTA_NAO_RESPONDIDO)) {
                    quantidadeRespostas += getQuantidadeRespotas(tipoResposta, questoesMarcadas.get(i), produtores, todosPeriodos, ini, fim, r);
                } else {
                    quantidadeRespostas += getQuantidadeRespotas(tipoResposta, questoesMarcadas.get(i), produtores, todosPeriodos, ini, fim, r);
                }
                if (porcenResult != null) {
                    getPorcentagemRespotas(quantidadeRespostas, produtores, resposta, r);
                }
            }
            result.add(r);
        }
        //Exibir qual periodo foi marcado
        String periodo = "de " + getPrimeiraDataQuestionario(produtores) + " a " + getUltimaDataQuestionario(produtores);
        if (todosPeriodos == null) {
            periodo = "de " + dataIni + " a " + dataFim;
        }
        //setar valores na sessão
        session.setAttribute("periodo", periodo);
        session.setAttribute("relAvGeral", getAvaliacaoGeral(result));
        session.setAttribute("relAvReprodutiva", getAvaliacaoReprodutiva(result));
        session.setAttribute("relAvSanitaria", getAvaliacaoSanitaria(result));
        session.setAttribute("relAvInstalacao", getAvaliacaoInstalacao(result));
        session.setAttribute("relAvOrganizacional", getAvaliacaoOrganizacional(result));
        session.setAttribute("relAvNutricional", getAvaliacaoNutricional(result));
        session.setAttribute("comparacao", comparacao);
        session.setAttribute("quantResult", quantResut);
        session.setAttribute("porcentResult", porcenResult);
        session.setAttribute("respostaNumerica", resposta);
        session.setAttribute("tipoResposta", tipoResposta);
        if (questaoEstimavitivaMarcada) {
            session.setAttribute("AG3ou4", "marcada");
        }
        return "/visit/relatorio_ql_gerado.jsp";
    }

    private int validaCampos(String comparacao, String tdPeriodos, String dataIni, String dataFim, String quantResult, String porcentResul, String tipoResposta) {

        if ((tipoResposta == null || tipoResposta.trim().isEmpty() || tipoResposta.equals("null")) && (comparacao == null || comparacao.trim().isEmpty())) {
            return -1;
        }

        if ((comparacao == null || comparacao.trim().isEmpty()) && (tdPeriodos == null || tdPeriodos.trim().isEmpty()) && (dataIni == null || dataIni.trim().isEmpty()) && (dataFim == null || dataFim.trim().isEmpty())
                && (quantResult == null || quantResult.trim().isEmpty()) && (porcentResul == null || porcentResul.trim().isEmpty()) && (tipoResposta == null || tipoResposta.trim().isEmpty())) {
            return -5;
        }
        if ((comparacao == null || comparacao.trim().isEmpty()) && ((porcentResul == null || porcentResul.trim().isEmpty()) && (quantResult == null || quantResult.trim().isEmpty()))) {
            return -7;
        }

        if ((tdPeriodos == null || tdPeriodos.trim().isEmpty()) && ((dataIni == null || dataIni.trim().isEmpty()) && (dataFim == null || dataFim.trim().isEmpty()))) {
            return -2;
        }
        return 1;
    }

    private boolean validaData(Date ini, Date fim, List<Produtor> prods) {

        if (ini == null || fim == null) {
            return false;
        }
        if (ini.after(fim)) {
            return false;
        }
        for (Produtor p : prods) {
            List<Visita> visitas = p.getVisitas();
            for (Visita a : visitas) {
                if (!a.hasQuestionarioQualitativo()) {
                    continue;
                }
                Date visi = a.getData();
                if ((visi.before(fim) || visi.equals(fim)) && (visi.after(ini) || visi.equals(ini))) {
                    return true;
                }
            }
        }
        return false;
    }

    void getMediaValorQuestaoNumeerica(String questao, List<Produtor> prods, String tdPeriodo, Date ini, Date fim, RelatorioQualitativoResult r) {
        double AG3 = 0d;
        double AG4 = 0d;
        for (Produtor prod : prods) {
            List<Visita> visitas = prod.getVisitas();
            for (Visita v : visitas) {
                if (!v.hasQuestionarioQualitativo()) {
                    continue;
                }
                QuestionarioQualitativo ql = v.getQuestionarioQualitativo();
                Date visi = v.getData();
                if ((tdPeriodo != null) || ((visi.after(ini) || visi.equals(ini)) && (visi.before(fim) || visi.equals(fim)))) {


                    String value = ql.getRespostaPorCodigo(questao);
                    if (!value.equalsIgnoreCase(RelatorioQualitativoResult.RESPOSTA_NAO_RESPONDIDO)) {
                        if (questao.equals("AG3")) {
                            AG3 += new Double(value);
                        }
                        if (questao.equals("AG4")) {
                            AG4 += new Double(ql.getRespostaNumericaPorCodigo(questao));
                        }
                    }
                }
            }
        }

        if (questao.equals("AG3")) {
            r.addInformacaoPorcentagem(RelatorioQualitativoResult.VALOR_RESPOSTA_AG3, (AG3 / new Double((double) prods.size())));
        }
        if (questao.equals("AG4")) {
            r.addInformacaoPorcentagem(RelatorioQualitativoResult.VALOR_RESPOSTA_AG4, (AG4 / new Double((double) prods.size())));
        }
    }

    int getQuantidadeRespotas(String resposta, String questao, List<Produtor> prods, String tdPeriodo, Date ini, Date fim, RelatorioQualitativoResult r) {
        int quantidade = 0;
        for (Produtor prod : prods) {
            List<Visita> visitas = prod.getVisitas();
            for (Visita v : visitas) {
                if (!v.hasQuestionarioQualitativo()) {
                    continue;
                }
                QuestionarioQualitativo ql = v.getQuestionarioQualitativo();
                Date visi = v.getData();
                if ((tdPeriodo != null) || ((visi.after(ini) || visi.equals(ini)) && (visi.before(fim) || visi.equals(fim)))) {
                    if (resposta.equals(ql.getRespostaPorCodigo(questao))) {
                        quantidade++;
                    }
                }
            }
        }
        if (resposta.equals(RelatorioQualitativoResult.RESPOSTA_NAO_RESPONDIDO)) {
            r.addInformacaoQuantidade(RelatorioQualitativoResult.VALOR_RESPOSTA_NAO_RESPONDIDO, quantidade);
        } else if (resposta.equals(RelatorioQualitativoResult.RESPOSTA_NAO)) {
            r.addInformacaoQuantidade(RelatorioQualitativoResult.VALOR_RESPOSTA_NAO, quantidade);
        } else if (resposta.equals(RelatorioQualitativoResult.RESPOSTA_SIM)) {
            r.addInformacaoQuantidade(RelatorioQualitativoResult.VALOR_RESPOSTA_SIM, quantidade);
        } else {
            r.addInformacaoQuantidade(RelatorioQualitativoResult.VALOR_RESPOSTA_SIM_ADEQUADAMENTE, quantidade);
        }

        return quantidade;
    }

    void getPorcentagemRespotas(int totalRespostas, List<Produtor> prods, Integer resposta, RelatorioQualitativoResult r) {
        //int totalResponderam = this.getNumeroProdutoresQueResponderamUmaQuestao(resposta, questao, prods, tdPeriodo, ini, fim);
        Double total = new Double((double) prods.size());
        Double nRespostas = new Double(totalRespostas);
        Double porcentagem = new Double((nRespostas * 100D) / total);
        r.addInformacaoPorcentagem(resposta, porcentagem);
    }

    void getComparacao(String questao, List<Produtor> prods, String tdPeriodo, Date ini, Date fim, RelatorioQualitativoResult r) {

        int total = getQuantidadeRespotas(RelatorioQualitativoResult.RESPOSTA_NAO_RESPONDIDO, questao, prods, tdPeriodo, ini, fim, r);
        getPorcentagemRespotas(total, prods, RelatorioQualitativoResult.VALOR_RESPOSTA_NAO_RESPONDIDO, r);
        total = getQuantidadeRespotas(RelatorioQualitativoResult.RESPOSTA_NAO, questao, prods, tdPeriodo, ini, fim, r);
        getPorcentagemRespotas(total, prods, RelatorioQualitativoResult.VALOR_RESPOSTA_NAO, r);
        total = getQuantidadeRespotas(RelatorioQualitativoResult.RESPOSTA_SIM, questao, prods, tdPeriodo, ini, fim, r);
        getPorcentagemRespotas(total, prods, RelatorioQualitativoResult.VALOR_RESPOSTA_SIM, r);
        total = getQuantidadeRespotas(RelatorioQualitativoResult.RESPOSTA_SIM_ADEQUADAMENTE, questao, prods, tdPeriodo, ini, fim, r);
        getPorcentagemRespotas(total, prods, RelatorioQualitativoResult.VALOR_RESPOSTA_SIM_ADEQUADAMENTE, r);
    }

    int getNumeroProdutoresQueResponderamUmaQuestao(String resposta, String questao, List<Produtor> prods, String tdPeriodo, Date ini, Date fim) {

        int quantidade = 0;
        for (Produtor prod : prods) {
            List<Visita> visitas = prod.getVisitas();
            for (Visita v : visitas) {
                if (!v.hasQuestionarioQualitativo()) {
                    continue;
                }
                QuestionarioQualitativo ql = v.getQuestionarioQualitativo();
                Date visi = v.getData();
                if ((tdPeriodo != null) || ((visi.after(ini) || visi.equals(ini)) && (visi.before(fim) || visi.equals(fim)))) {
                    if (!ql.getRespostaPorCodigo(questao).equals(RelatorioQualitativoResult.RESPOSTA_NAO_RESPONDIDO)) {
                        quantidade++;
                    }
                }
            }
        }
        return quantidade;
    }

    List<RelatorioQualitativoResult> getAvaliacaoGeral(List<RelatorioQualitativoResult> result) {
        List<RelatorioQualitativoResult> relAvGeral = new ArrayList<RelatorioQualitativoResult>();
        for (RelatorioQualitativoResult r : result) {
            if (r.getQuestao().contains("AG")) {
                relAvGeral.add(r);
            }
        }
        return relAvGeral;
    }

    List<RelatorioQualitativoResult> getAvaliacaoNutricional(List<RelatorioQualitativoResult> result) {
        List<RelatorioQualitativoResult> relAvNutricional = new ArrayList<RelatorioQualitativoResult>();
        for (RelatorioQualitativoResult r : result) {
            if (r.getQuestao().contains("AN")) {
                relAvNutricional.add(r);
            }
        }
        return relAvNutricional;
    }

    List<RelatorioQualitativoResult> getAvaliacaoOrganizacional(List<RelatorioQualitativoResult> result) {
        List<RelatorioQualitativoResult> relAvOrganizacional = new ArrayList<RelatorioQualitativoResult>();
        for (RelatorioQualitativoResult r : result) {
            if (r.getQuestao().contains("AO")) {
                relAvOrganizacional.add(r);
            }
        }
        return relAvOrganizacional;
    }

    List<RelatorioQualitativoResult> getAvaliacaoReprodutiva(List<RelatorioQualitativoResult> result) {
        List<RelatorioQualitativoResult> relAvReprodutiva = new ArrayList<RelatorioQualitativoResult>();
        for (RelatorioQualitativoResult r : result) {
            if (r.getQuestao().contains("AR")) {
                relAvReprodutiva.add(r);
            }
        }
        return relAvReprodutiva;
    }

    List<RelatorioQualitativoResult> getAvaliacaoInstalacao(List<RelatorioQualitativoResult> result) {
        List<RelatorioQualitativoResult> relAvInstalacao = new ArrayList<RelatorioQualitativoResult>();
        for (RelatorioQualitativoResult r : result) {
            if (r.getQuestao().contains("AI")) {
                relAvInstalacao.add(r);
            }
        }
        return relAvInstalacao;
    }

    List<RelatorioQualitativoResult> getAvaliacaoSanitaria(List<RelatorioQualitativoResult> result) {
        List<RelatorioQualitativoResult> relAvSanitaria = new ArrayList<RelatorioQualitativoResult>();
        for (RelatorioQualitativoResult r : result) {
            if (r.getQuestao().contains("AS")) {
                relAvSanitaria.add(r);
            }
        }
        return relAvSanitaria;
    }

    public String getPrimeiraDataQuestionario(List<Produtor> produtores) {

        Date primeira = new Date();
        List<Visita> visitas;
        for (Produtor p : produtores) {
            visitas = p.getVisitas();
            if (visitas == null) {
                continue;
            }
            for (Visita v : visitas) {
                if (!v.hasQuestionarioQualitativo()) {
                    continue;
                }
                Date dAux = v.getData();
                if (primeira.after(dAux)) {
                    primeira = dAux;
                }
            }
        }
        return UtilAdrs.treatToString(primeira);
    }

    /*
     * Método que retorna a data da ultima visita, caso o Admin selecione a opções todos os periodos
     */
    public String getUltimaDataQuestionario(List<Produtor> produtores) {

        Date ultima = null;
        List<Visita> visitas;
        for (Produtor p : produtores) {
            visitas = p.getVisitas();
            if (visitas == null) {
                continue;
            }
            for (Visita v : visitas) {
                if (!v.hasQuestionarioQualitativo()) {
                    continue;
                }
                Date dAux = v.getData();
                if (ultima == null || ultima.before(dAux)) {
                    ultima = dAux;
                }
            }
        }
        return UtilAdrs.treatToString(ultima);
    }
}
